#! /usr/bin/env python
# -*- coding: utf-8 -*-
"""NM64 station read input data in CosRay format

Copyright (C) 2011-2014 Christian T. Steigies <steigies@physik.uni-kiel.de>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

__author__ = "Christian T. Steigies <steigies@physik.uni-kiel.de>"
__license__ = "GPL License"

## --------------------------------------------------------------------------
import os
import calendar # monthrange, isleap
from datetime import datetime, date, time
import urllib2

from nmdb.tools.datetool import year2
from nmdb.station.station_data import check_data, check_pressure

## --------------------------------------------------------------------------
def cosray_names(data_path, data_type, station, year, month):
    if data_type in ["1m", "ori"]:
        file_c = "%s/ftp_nm1/c/%4ic/%4i%s/%02i%02i%s.w1c" \
                % (data_path, year, year, station, year2(year), month, station)
        file_p = "%s/ftp_nm1/p/%4ip/%4i%s/%02i%02i%s.w1p" \
                % (data_path, year, year, station, year2(year), month, station)
        file_u = "%s/ftp_nm1/u/%4iu/%4i%s/%02i%02i%s.w1u" \
                % (data_path, year, year, station, year2(year), month, station)

    elif data_type in ["1h"]:
        file_c = "%s/ftp_nm/c/%4ic/%4i%s/%02i%02i%s.c0c" \
                % (data_path, year, year, station, year2(year), month, station)
        file_p = "%s/ftp_nm/p/%4ip/%4i%s/%02i%02i%s.c0p" \
                % (data_path, year, year, station, year2(year), month, station)
        file_u = "%s/ftp_nm/u/%4iu/%4i%s/%02i%02i%s.c0u" \
                % (data_path, year, year, station, year2(year), month, station)
    else:
        raise ValueError  # unknown data_type

    return (file_c, file_p, file_u)

## --------------------------------------------------------------------------
def read_1m(data_path, station, pressure, countrate, year, month, day=None):
    """read in one month of minutely data from ASCII files
    and return data in NMDB format
    if day is given, return data only for this day
    TODO: if DOS uppercase of subdirectories after data_path
    """

    data = []
    data_type = "1m"
    (file_c, file_p, file_u) = cosray_names(data_path, data_type, station, year, month)
    useftp = data_path[0:3] == "ftp"
    if False:  #options.verbose > 1:
        print file_c
        print file_p
        print file_u
        print useftp

    try:
        if useftp:
            myfile_c = urllib2.urlopen(file_c)
            myfile_p = urllib2.urlopen(file_p)
            myfile_u = urllib2.urlopen(file_u)
        else:
            myfile_c = open(file_c, "r")
            myfile_p = open(file_p, "r")
            myfile_u = open(file_u, "r")
    except IOError:
        # any of the three files could not exist
        print "error opening file:\n\t    %s\n\t or %s\n\t or %s" % (file_c, file_p, file_u)
        # TODO workaround for missing U or P data
        return None

    (dummy, days) = calendar.monthrange(year, month)
    for myday in range(1, days + 1):
        mydate = date(year, month, myday)
        for hour in range(0, 24):
            C = U = P = []
                
            for i in range(0, 5):
                line = myfile_c.readline()
                # basic checks if data is correct: start
                if (i < 4) and (len(line.split()) > 12):
                    print "error in corrected data"
                elif (i == 4):
                    this_my = line.split()[12:13][0]
                    if (len(this_my) == 4):
                        this_year = int(this_my[0:2])
                        this_month = int(this_my[2:4])
                    else:
                        pass
                    this_day = int(line.split()[13:14][0])
                    this_hour = int(float(line.split()[14:15][0]))

                    if (this_year != year2(year)):
                        print "wrong year", year2(year), this_year, int(this_year)
                    if (this_month != month):
                        print "wrong month", month, this_month, int(this_month)
                    if (this_day != myday):
                        print "wrong day", myday, this_day, int(this_day)
                    if (this_hour != hour):
                        print "wrong hour", hour,  line.split()[14:15]
                # basic checks if data is correct: stop
                C = C + line.split()
                        
                line = myfile_u.readline()
                # basic checks if data is correct: start
                if (i < 4) and (len(line.split()) > 12):
                    print "error in uncorrected data"
                # basic checks if data is correct: stop
                U = U + line.split()
                                    
                line = myfile_p.readline()
                # basic checks if data is correct: start
                if (i < 4) and (len(line.split()) > 12):
                    print "error in pressure data"
                # basic checks if data is correct: stop
                P = P + line.split()

            # one hour has been read in, process only if this day or all days are read in
            if day == None or myday == day:
                if (len(C) > 60) and (len(U) > 60) and (len(P) > 60):
                    for i in range(0, 60):
                        myinterval = 60
                        uncorr = round((float(U[i]) / myinterval), 3)
                        press = round((float(P[i]) / 10.), 3)
                        corr = round((float(C[i]) / myinterval), 3)
                        # round to three digits after the decimal

                        uncorr = check_data(uncorr, cr_min=countrate[0], cr_max=countrate[1])
                        press = check_pressure(press, p_min=pressure[0], p_max=pressure[1])
                        corr = check_data(corr, cr_min=countrate[0], cr_max=countrate[1])
                        ceff = corr

                        mytime = time(hour, i, 0)
                        mydatetime = datetime.combine(mydate, mytime)

                        if uncorr is None and press is None and corr is None and ceff is None:
                            pass  # No data? What about data gaps?
                        else:
                            data.append([  # order as in NMDB
                                mydatetime, myinterval, uncorr, ceff, corr, press
                                ])

                else:
                    raise ValueError  # error in 1m data
                                                
    myfile_c.close()
    myfile_p.close()
    myfile_u.close()

    return data

## --------------------------------------------------------------------------

def read_1h(data_path, station, pressure, countrate, year, month, day=None):
    """read in one month of hourly data from ASCII files
    and return data in NMDB format
    if day is given, return data only for this day
    TODO: if DOS uppercase of subdirectories after datapath
    TODO: fail if error in data checks"""

    data = []
    myinterval = 3600

    if station == "leik":
        station = "kiel"
        
    data_type = "1h"
    (file_c, file_p, file_u) = cosray_names(data_path, data_type, station, year, month)
    useftp = data_path[0:3] == "ftp"
    
    use_u = use_p = True
    try:
        if useftp:
            myfile_c = urllib2.urlopen(file_c)
        else:
            myfile_c = open(file_c, "r")
    except IOError:
        print "error opening %s" % (file_c)
        return None
        
    try:
        if useftp:
            myfile_p = urllib2.urlopen(file_p)
        else:
            myfile_p = open(file_p, "r")
    except IOError:
        print "error opening %s" % (file_p)
        use_p = False
        
    try:
        if useftp:
            myfile_u = urllib2.urlopen(file_u)
        else:
            myfile_u = open(file_u, "r")
    except IOError:
        print "error opening %s" % (file_u)
        use_u = False
            
    (dummy, days) = calendar.monthrange(year, month)

    # skip comment lines
    for i in range(0, 7):
        line = myfile_c.readline()
        if use_p:
            line = myfile_p.readline()
        if use_u:
            line = myfile_u.readline()

    for myday in range(1, days+1):
        mydate = date(year, month, myday)
        for hour in range(0, 24):               
            C = O = U = P = []
        for i in (1, 2):
            line = myfile_c.readline()

            C = C + line.split()
            if use_p:
                line = myfile_p.readline()
                P = P + line.split()
            if use_u:
                line = myfile_u.readline()
                U = U + line.split()

        # one day has been read in, process only if this day or all days are read in
        if day == None or myday == day:
            if (len(C) > 24):
                for i in range(0, 24):
                    if use_u:
                        uncorr = round(100. * (float(U[i]) / myinterval), 3)
                    else:
                        uncorr = 0
                    if use_p:
                        press = round((float(P[i]) / 10.), 3)
                    else:
                        press = 0
                    corr = round(100. * (float(C[i]) / myinterval), 3)
                    # round to three digits after the decimal

                    uncorr = check_data(uncorr, cr_min=countrate[0], cr_max=countrate[1])
                    press = check_pressure(press, p_min=pressure[0], p_max=pressure[1])
                    corr = check_data(corr, cr_min=countrate[0], cr_max=countrate[1])
                    ceff = corr

                    mytime = time(i, 0, 0)
                    mydatetime = datetime.combine(mydate, mytime)

                    if uncorr is None and press is None and corr is None and ceff is None:
                        pass  # No data? What about data gaps?
                    else:
                        data.append([  # order as in NMDB
                                    mydatetime, myinterval, uncorr, ceff, corr, press
                                    ])

            else:
                raise ValueError  # error in 1h data
                
    myfile_c.close()
    if use_p:
        myfile_p.close()
    if use_u:
        myfile_u.close()

    return data


## --------------------------------------------------------------------------
if __name__ == "__main__":
    print "This is the NMDB station read_cosray module."

    data_path = '~/data/cosray'
    data_path = os.path.expanduser(data_path)
    data_type = "1m"
    data_type = "1h"
    station = "kiel"
    year = 2013
    month = 10
    pressure = [950., 1050.]  # 982 - 1028
    countrate = [50., 1000.]

    #data = read_1h(data_path, station, pressure, countrate, year, month, 1)
    data = read_1m(data_path, station, pressure, countrate, year, month, 1)
    for i in data:
        print i
